"""
策略基类模块，定义了所有策略需要实现的接口
"""
from abc import ABC, abstractmethod
import pandas as pd
from typing import Dict, Any, Optional, List, Tuple, Union
from datetime import datetime
import logging
from services.exchange.interface import ExchangeType
# 直接使用合约配置适配器
from services.contract_config_adapter import get_mark_price_round, get_quanto_multiplier, format_price

logger = logging.getLogger(__name__)

class StrategyBase:
    """
    策略基类，所有策略都应继承此类
    """
    
    def __init__(self, symbol: str, parameters: Dict[str, Any] = None):
        """初始化策略基类
        
        Args:
            symbol: 交易对符号
            parameters: 策略参数字典
        """
        self.symbol = symbol
        self.parameters = parameters or {}
        self.logger = logging.getLogger(f"{self.__class__.__name__}_{symbol}")
        
        # 从参数中获取硬止损百分比
        self.hard_stop_loss_pct = self.parameters.get('hard_stop_loss_pct', 0.0)
        
        # 默认使用Gate交易所
        self.exchange = ExchangeType.GATE
        
        # 获取合约精度信息
        self.mark_price_round = self._get_price_precision(self.exchange)
        self.quanto_multiplier = self._get_quanto_multiplier(self.exchange)
        
        self.logger.info(f"策略初始化: {symbol}, 价格精度: {self.mark_price_round}, 合约乘数: {self.quanto_multiplier}")
        
    def _get_price_precision(self, exchange: ExchangeType) -> int:
        """获取价格精度
        
        从合约配置适配器获取mark_price_round，如果不存在，则使用默认值8
        
        Args:
            exchange: 交易所类型
            
        Returns:
            价格精度
        """
        mark_price_round = get_mark_price_round(exchange, self.symbol)
        if mark_price_round is None:
            return 8  # 默认精度
            
        try:
            return int(mark_price_round)
        except (ValueError, TypeError):
            self.logger.warning(f"无法将mark_price_round转换为整数: {mark_price_round}，使用默认值8")
            return 8
    
    def _get_quanto_multiplier(self, exchange: ExchangeType) -> float:
        """获取合约乘数
        
        从合约配置适配器获取quanto_multiplier，如果不存在，则使用默认值1.0
        
        Args:
            exchange: 交易所类型
            
        Returns:
            合约乘数
        """
        quanto_multiplier = get_quanto_multiplier(exchange, self.symbol)
        print(f"quanto_multiplier: {quanto_multiplier}")
        if quanto_multiplier is None:
            return 1.0  # 默认乘数
            
        try:
            return float(quanto_multiplier)
        except (ValueError, TypeError):
            self.logger.warning(f"无法将quanto_multiplier转换为浮点数: {quanto_multiplier}，使用默认值1.0")
            return 1.0
    
    def base_format_price(self, price: float) -> float:
        """格式化价格，按照合约精度进行四舍五入
        
        Args:
            price: 原始价格
            
        Returns:
            格式化后的价格
        """
        return format_price(self.exchange, self.symbol, price)
    
    def prepare_data(self, raw_data: pd.DataFrame) -> pd.DataFrame:
        """准备数据，计算指标等
        
        此方法需要被子类重写
        
        Args:
            raw_data: 原始K线数据
            
        Returns:
            处理后的数据
        """
        raise NotImplementedError("子类必须实现prepare_data方法")
    
    async def check_entry_signal(self, data: pd.DataFrame) -> Tuple[bool, Dict[str, Any]]:
        """检查开仓信号
        
        此方法需要被子类重写
        
        Args:
            data: 经过prepare_data处理后的数据
            
        Returns:
            (是否有信号, 信号详情)
        """
        raise NotImplementedError("子类必须实现check_entry_signal方法")
    
    async def check_exit_signal(self, data: pd.DataFrame, position_direction: str = None, entry_price: float = None) -> Tuple[bool, Dict[str, Any]]:
        """检查平仓信号
        
        此方法需要被子类重写
        
        Args:
            data: 经过prepare_data处理后的数据
            position_direction: 持仓方向
            entry_price: 开仓价格
            
        Returns:
            (是否有信号, 信号详情)
        """
        raise NotImplementedError("子类必须实现check_exit_signal方法")
    
    def calculate_position_size(self, margin: float, leverage: float, price: float) -> int:
        """计算仓位大小(合约张数)
        
        Args:
            margin: 保证金
            leverage: 杠杆倍数
            price: 当前价格
            
        Returns:
            仓位大小(合约张数)，至少为1张
        """
        # 根据公式计算合约张数: (保证金*杠杆)/(当前价格*币种quanto_multiplier)
        position_size = (margin * leverage) / (price * self.quanto_multiplier)
        
        # 向下取整，确保是整数张，且至少为1张
        return max(1, int(position_size))
    